#include "LRUCache.hpp"
#include <vector>
#include <cmath>
#include <thread>

template <typename Key, typename Value>
class HashLRUCache
{
public:
    HashLRUCache(int sliceNum, int capacity) : m_sliceNum(sliceNum > 0 ? sliceNum : std::thread::hardware_concurrency()), m_capacity(capacity)
    {
        int sliceSize = std::ceil(m_capacity / (double)sliceNum);
        for (int i = 0; i < sliceNum; i++)
        {
            sliceCaches.emplace_back(new LRUCache<Key, Value>(sliceSize));
        }
    }

    void put(const Key& key, const Value& value)
    {
        size_t index = Hash(key) % m_sliceNum;
        sliceCaches[index]->put(key, value);
    }

    bool get(const Key& key, Value& value)
    {
        size_t index = Hash(key) % m_sliceNum;
        return sliceCaches[index]->get(key, value);
    }

    Value get(const Key& key)
    {
        Value value;
        get(key, value);
        return value;
    }
private:
    size_t Hash(const Key& key)
    {
        std::hash<Key> hashFunc;
        return hashFunc(key);
    }
private:
    int m_sliceNum;
    int m_capacity;
    std::vector<std::unique_ptr<LRUCache<Key, Value>>> sliceCaches;
};